package com.campus.food.config;

import com.campus.food.security.JwtAuthenticationFilter;
import com.campus.food.security.RestAccessDeniedHandler;
import com.campus.food.security.RestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * Spring Security配置类
 * 
 * @author Claude3.7 Sonnet
 * @since 2025-05-29
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Autowired
    private RestAccessDeniedHandler accessDeniedHandler;

    @Autowired
    private RestAuthenticationEntryPoint authenticationEntryPoint;
    
    /**
     * 密码编码器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    /**
     * 跨域配置
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        
        // 允许的源
        configuration.setAllowedOriginPatterns(Arrays.asList("*"));
        
        // 允许的HTTP方法
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        
        // 允许的请求头
        configuration.setAllowedHeaders(Arrays.asList("*"));
        
        // 允许携带凭证
        configuration.setAllowCredentials(true);
        
        // 预检请求的缓存时间
        configuration.setMaxAge(3600L);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        
        return source;
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // 禁用CSRF
            .csrf().disable()
            
            // 启用跨域
            .cors().configurationSource(corsConfigurationSource())
            
            .and()
            
            // 配置会话管理为无状态
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            
            .and()
            
            // 配置请求授权
            .authorizeRequests()
            
            // 公开接口，无需认证
            .antMatchers(
                    "/api/banners/active",
                "/api/users/login", // 认证相关接口
                "/api/upload/**", // 文件上传
                "/api/file/**", // 文件访问
                "/api/file/merchant/**", // 商家图片访问
                "/api/file/food/**", // 食品图片访问
                "/api/file/avatar/**", // 用户头像访问
                "/api/file/review/**", // 评论图片访问
                "/api/file/common/**", // 通用文件访问
                "/api/merchants/*", // 商家详情
                "/api/foods/category/*/*", // 分类查商品
                "/api/foods/categories/**", // 食物分类
                "/api/foods/merchant/{merchantId}", // 根据商家获取菜品
                "/api/users/register",        // 注册接口
                "/api/public/**",         // 公开接口
                "/api/merchants/open",    // 营业中的商家列表
                "/api/foods/user/**",     // 用户端菜品接口
                "/swagger-ui/**",         // Swagger文档
                "/swagger-resources/**",
                "/v2/api-docs",
                "/webjars/**",
                "/favicon.ico",
                "/error"
            ).permitAll()
            
            // 用户相关接口，需要USER或更高权限
            .antMatchers("/api/users/**").hasAnyRole("USER", "MERCHANT", "ADMIN")
            .antMatchers("/api/addresses/**").hasAnyRole("USER", "MERCHANT", "ADMIN")
            .antMatchers("/api/cart/**").hasRole("USER")
            .antMatchers("/api/orders/user/**").hasAnyRole("USER","MERCHANT")
            .antMatchers("/api/reviews/user/**").hasRole("USER")
            
            // 商家相关接口，需要MERCHANT或ADMIN权限
            .antMatchers("/api/merchants/apply").hasAnyRole("USER","ADMIN")
            .antMatchers("/api/merchants/my/**").hasRole("MERCHANT")
            .antMatchers("/api/foods/merchant/**").hasRole("MERCHANT")
            .antMatchers("/api/orders/merchant/**").hasRole("MERCHANT")
            
            // 管理员相关接口，需要ADMIN权限
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .antMatchers("/api/merchants/admin/**").hasRole("ADMIN")
            .antMatchers("/api/orders/admin/**").hasRole("ADMIN")
            
            // 其他所有请求都需要认证
            .anyRequest().authenticated()
            
            .and()
            
            // 添加JWT过滤器
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
            
            // 禁用默认的登录页面
            .formLogin().disable()
            
            // 禁用HTTP Basic认证
            .httpBasic().disable()
            
            // 自定义异常处理
            .exceptionHandling()
            // 认证失败处理
            .authenticationEntryPoint(authenticationEntryPoint)
            // 权限不足处理
            .accessDeniedHandler(accessDeniedHandler);
    }

    /**
     * 自定义访问拒绝处理器
     */
    @Bean
    public RestAccessDeniedHandler accessDeniedHandler() {
        return new RestAccessDeniedHandler();
    }

    /**
     * 自定义认证入口点
     */
    @Bean
    public RestAuthenticationEntryPoint authenticationEntryPoint() {
        return new RestAuthenticationEntryPoint();
    }
} 